#!/bin/bash -e

source reporting.sh
CONFIG=/config/device/module_config.json

REPORT=/tmp/report.txt
LOG=/tmp/nmap.log
OPENPORTSLIST_LOG=/tmp/nmap.ports.log
REDACTED_LOG=/tmp/nmap.report.log

TEST_NAME="security.ports.nmap"
TEST_DESCRIPTION="Automatic TCP/UDP port scan using nmap"
SUMMARY=""

rm -f $LOG $REDACTED_LOG $OPENPORTSLIST_LOG $REPORT

if [ -f $CONFIG ]; then
    echo Extracting servers config from $CONFIG
else
    echo No module config $CONFIG.
fi

echo -e "\nPinging target $TARGET_IP"
ping -n -c 20 $TARGET_IP

echo -e "\nTesting target $TARGET_IP port 23 (telnet)"
nc -nzv $TARGET_IP -w 5 23 || true
nc -nzv $TARGET_IP -w 5 23 || true
sleep 1
nc -nzv $TARGET_IP -w 5 23 || true
sleep 1

option="-sT"
portslist=-p1-1024
if [ -f $CONFIG ]; then
  # get list of ports to be scanned from module_config.json
  ports="U:"
  for k in $(jq '.servers.udp.ports | keys | .[]' $CONFIG); do
    ports=$ports$k","
  done
  if [ $ports != "U:" ]; then
    option="$option -sU"
  fi   

  ports=$ports"T:"
  for k in $(jq '.servers.tcp.ports | keys | .[]' $CONFIG); do
    ports=$ports$k","
  done
  portslist=$(echo $ports | sed 's/"//g')
  if [ $portslist != "U:T:" ]; then
    portslist="-p$portslist"
  else
    portslist=-p1-1024
  fi
fi

echo -e "\nTesting target $TARGET_IP to check open ports $portslist"
nmap -v -n -T5 $option --host-timeout=4m --open $portslist -oG $LOG $TARGET_IP > /dev/null
cat $LOG

touch $REDACTED_LOG
cat $LOG | tee -a $REDACTED_LOG
touch $REPORT
touch $OPENPORTSLIST_LOG
rm -f .fail
openportslist=" - "
grep -oh '[0-9]*/open[^[:space:]]*' $LOG | while IFS=/ read -ra parts; do
    state=${parts[1]}
    if [ "$state" == open ]; then
        if [ -f $CONFIG ]; then
            port=${parts[0]}
            proto=${parts[2]}
            allowed=$(jq ".servers.$proto.ports.\"$port\".allowed" $CONFIG)
            if [ "$allowed" != true ]; then
                touch .fail
                echo Failing ${parts[*]} | sed 's/,$//' | tee -a $REDACTED_LOG
                echo ${parts[0]}"," | tee -a $OPENPORTSLIST_LOG
            else
                echo Allowing ${parts[*]} | sed 's/,$//' | tee -a $REDACTED_LOG
            fi
        else
            echo Open port ${parts[*]} | sed 's/,$//' | tee -a $REDACTED_LOG
            touch .fail
        fi
    fi
done

if [ -f .fail ]; then
    echo Open ports:
    cat $REDACTED_LOG
    result=fail
    SUMMARY="Some disallowed ports are open: `cat $OPENPORTSLIST_LOG | sed 's/,$//'`"
else
    echo No invalid ports found. | tee -a $REDACTED_LOG
    result=pass
    SUMMARY="Only allowed ports found open."
fi

RESULT_AND_SUMMARY="RESULT $result $TEST_NAME $SUMMARY"

write_out_result $REPORT \
                 "$TEST_NAME" \
                 "$TEST_DESCRIPTION" \
                 "$(cat $REDACTED_LOG)" \
                 "$RESULT_AND_SUMMARY"
